#include <math.h>

#include "../log.h"
#include "mips.h"
#include "int.h"
#include "intfpu.h"

#define F(i)   (cpu.f[i])
#define FI(i)  (*(u32*)&cpu.f[i])
#define FsI(i) (*(s32*)&cpu.f[i])

void int_lwc1(u32 op)
{
    FI(_FT) = mem_read32(MEMADDR);
}

void int_swc1(u32 op)
{
    mem_write32(MEMADDR, FI(_FT));
}

void int_mfc1(u32 op)
{
    R(_RT) = FI(_FS);
}

void int_cfc1(u32 op)
{
    R(_RT) = cpu_readFCR(_FS);
}

void int_mtc1(u32 op)
{
    FI(_FS) = R(_RT);
}

void int_ctc1(u32 op)
{
    cpu_writeFCR(_FS, R(_RT));
}

void int_sqrt(u32 op)
{
    F(_FD) = sqrtf(F(_FS));
}

void int_abs(u32 op)
{
    F(_FD) = fabsf(F(_FS));
}

void int_mov(u32 op)
{
    F(_FD) = F(_FS);
}

void int_neg(u32 op)
{
    F(_FD) = -F(_FS);
}

void int_round(u32 op)
{
    FsI(_FD) = (s32)floorf(F(_FS) + 0.5f);
}

void int_trunc(u32 op)
{
    FsI(_FD) = (F(_FS) >= 0) ? (s32)floorf(F(_FS)) : (s32)ceilf(F(_FS));
}

void int_ceil(u32 op)
{
    FsI(_FD) = (s32)ceilf(F(_FS));
}

void int_floor(u32 op)
{
    FsI(_FD) = (s32)floorf(F(_FS));
}

void int_cvtsw(u32 op)
{
    F(_FD) = (float)FsI(_FS);
}

void int_cvtws(u32 op)
{
    FsI(_FD) = (s32)F(_FS);
}

void int_eq(u32 op)
{
    cpu_setFcc((F(_FS) == F(_FT)));
}

void int_lt(u32 op)
{
    cpu_setFcc((F(_FS) < F(_FT)));
}

void int_nge(u32 op)
{
    cpu_setFcc((F(_FS) < F(_FT)));
}

void int_le(u32 op)
{
    cpu_setFcc((F(_FS) <= F(_FT)));
}

void int_ngt(u32 op)
{
    cpu_setFcc((F(_FS) <= F(_FT)));
}

void int_fadd(u32 op)
{
    F(_FD) = F(_FS) + F(_FT);
}

void int_fsub(u32 op)
{
    F(_FD) = F(_FS) - F(_FT);
}

void int_fmul(u32 op)
{
    F(_FD) = F(_FS) * F(_FT);
}

void int_fdiv(u32 op)
{
    F(_FD) = F(_FS) / F(_FT);
}

void int_bc1f(u32 op)
{
    if (!cpu_getFcc())
        cpu_delayBranchTo(BRANCHADDR);
}

void int_bc1t(u32 op)
{
    if (cpu_getFcc())
        cpu_delayBranchTo(BRANCHADDR);
}

void int_bc1fl(u32 op)
{
    if (!cpu_getFcc())
        cpu_delayBranchTo(BRANCHADDR);
    else
        PC += 4;
}

void int_bc1tl(u32 op)
{
    if (cpu_getFcc())
        cpu_delayBranchTo(BRANCHADDR);
    else
        PC += 4;
}
